#include "JsonRpcRequest.h"

JsonRpcRequest::JsonRpcRequest()
    : JsonRpcRequest(QVariant(), "", QJsonObject())
{
}

JsonRpcRequest::JsonRpcRequest(const QVariant& id)
    : JsonRpcRequest(id, "", QJsonObject())
{
}

JsonRpcRequest::JsonRpcRequest(const QVariant& id, const QString& method)
    : JsonRpcRequest(id, method, QJsonObject())
{
}

JsonRpcRequest::JsonRpcRequest(const QVariant& id, const QString& method, const QJsonObject& params)
    : JsonRpcMessage()
    , mMethod(method)
    , mParams(params)
{
    mId = id;
}

JsonRpcRequest::~JsonRpcRequest()
{
}

QString JsonRpcRequest::method() const
{
    return mMethod;
}

void JsonRpcRequest::setMethod(const QString& method)
{
    mMethod = method;
}

QJsonObject JsonRpcRequest::params() const
{
    return mParams;
}

void JsonRpcRequest::setParams(const QJsonObject& params)
{
    if (params != mParams) {
        mParams = params;
    }
}

bool JsonRpcRequest::hasParams() const
{
    return !mParams.isEmpty();
}

QJsonObject JsonRpcRequest::toJson() const
{
    QJsonObject json;
    json["jsonrpc"] = jsonrpc();
    json["method"] = mMethod;
    
    if (hasId()) {
        if (id().type() == QVariant::String) {
            json["id"] = id().toString();
        } else if (id().canConvert<double>()) {
            json["id"] = id().toDouble();
        }
    }
    
    if (hasParams()) {
        json["params"] = mParams;
    }
    
    return json;
}

JsonRpcRequest JsonRpcRequest::fromJson(const QJsonObject& json, bool* ok)
{
    JsonRpcRequest request;
    
    // Validate required fields
    if (!json.contains("jsonrpc") || json["jsonrpc"].toString() != "2.0") {
        if (ok) *ok = false;
        return request;
    }
    
    if (!json.contains("method") || !json["method"].isString()) {
        if (ok) *ok = false;
        return request;
    }
    
    // Set method
    request.mMethod = json["method"].toString();
    
    // Set ID if present
    if (json.contains("id")) {
        if (json["id"].isString()) {
            request.mId = json["id"].toString();
        } else if (json["id"].isDouble()) {
            request.mId = json["id"].toDouble();
        }
    }
    
    // Set parameters if present
    if (json.contains("params")) {
        if (json["params"].isObject()) {
            request.mParams = json["params"].toObject();
        } else {
            // Invalid parameters type
            if (ok) *ok = false;
            return request;
        }
    }
    
    if (ok) *ok = true;
    return request;
}

bool JsonRpcRequest::isValid() const
{
    if ( (jsonrpc() == "2.0")                                       &&
         (id().canConvert<QString>() || id().canConvert<double>())  &&
         (!mMethod.isEmpty())
       )
        return true;

    return false;
}
